import sqlite3;
import os;
import gzip
import xml.etree.ElementTree as ET
import re

import database

packages_path='/var/cache/dnf/packages.db'
#packages_path='./packages.db'

require2required=dict()
installed=set()
xmlns="http://linux.duke.edu/metadata/common" 
xmlns_rpm="http://linux.duke.edu/metadata/rpm"


def find_all_subdirs(path):
    dirs=[]
    for item in os.scandir(path):
        if item.is_dir():
          dirs.append(item.path)
    return dirs
def find_all_files(path):
    files=[]
    for item in os.scandir(path):
        if item.is_file():
          files.append(item.path)
    return files

def find_one_file(pattern,path):
    files=find_all_files(path)
    for f in files:
        if pattern in f:
            return f
    return None

def split_package_fullname(package_fullname):
    """
    Pass in a standard style rpm fullname 
    
    Return a name, version, release, epoch, arch, e.g.::
        foo-1.0-1.i386.rpm returns foo, 1.0, 1, i386
        1:bar-9-123a.ia64.rpm returns bar, 9, 123a, 1, ia64
    """
    
    archIndex = package_fullname.rfind('.')
    arch = package_fullname[archIndex+1:]

    relIndex = package_fullname[:archIndex].rfind('-')
    rel = package_fullname[relIndex+1:archIndex]

    verIndex = package_fullname[:relIndex].rfind('-')
    ver = package_fullname[verIndex+1:relIndex]

    epochIndex = package_fullname.find(':')
    if epochIndex == -1:
        epoch = ''
    else:
        epoch = package_fullname[:epochIndex]
        
    name = package_fullname[epochIndex + 1:verIndex]
    return name, ver, rel, epoch, arch

def is_required(requirement,package_fullname):#not used yet
    splited_name=split_package_fullname(package_fullname)
    requirement_data=requirement['flag'],requirement['name'],
    requirement['rel'],requirement['epoch'],requirement['arch']

    if splited_name[0] != requirement['name']:
        return False
    if 'flag' in requirement:
        if requirement['flag'] == 'EQ':
            return requirement_data[1:]==requirement[0:]
        elif requirement['flag'] == 'LT':
            return requirement

def parse_requires(primary):
    input = gzip.open(primary, 'r')
    tree = ET.parse(input)
    packages=tree.findall("{http://linux.duke.edu/metadata/common}package")
    require_records=[]
    for package in packages:
        package_name=package.find('{http://linux.duke.edu/metadata/common}name').text
        if package_name not in installed:
            continue;
        format=package.find('{http://linux.duke.edu/metadata/common}format')
        if format is None:
            continue;
        requires=format.find('{http://linux.duke.edu/metadata/rpm}requires')
        if requires is None:
            continue;
        for require in requires.findall('{http://linux.duke.edu/metadata/rpm}entry'):
            require.attrib['package']=package_name
            require_records.append(require.attrib)
    database.insert_require(require_records)


def get_all_requires():
    database.reset_DB()
    repos=find_all_subdirs('/var/cache/dnf/')
    for repo in repos:
        repo_data=repo+'/repodata'
        if repo_data in find_all_subdirs(repo):
            primary=find_one_file('-primary.xml.gz',repo_data)
            if primary != None:
                parse_requires(primary)


                

def get_installed_packages():
    try:
        conn = sqlite3.connect(packages_path)
        cur=conn.cursor()
        cur.execute('SELECT * FROM installed')
        result=cur.fetchall()
        global installed
        global require2required
        for package in result:
            installed.add(split_package_fullname(package[0])[0])
        cur.close()
        conn.close()
    except:
        print("packages not find")
        exit()

    

def query_one(package):
    if package not in installed:
        print("%s is not installed on this computer." %package)
        return
    print("%s is required by:" %package)
    for name in database.find_required(package):
        print("\t%s" %name)

if __name__=='__main__':
    database.reset_DB()
    get_installed_packages()
    get_all_requires()